﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Qiang.Topology.Geometries;

namespace Qiang.Data
{
    /// <summary>
    /// 弧段类
    /// </summary>
    [Serializable]
    public class SegmentShape : Shape,ISegmentShape
    {

        # region 初始化

        //弧段的构成：起始节点、终止节点、顶点集合、左右多边形。
        //规定：弧段是有方向的，正方向为起始节点到终止节点的方向。
        //弧段是不可自相交的。
        //按正方向左边的多边形为弧段的左多边形，右边的多边形为右多边形。


      
        /// <summary>
        /// 
        /// </summary>
        /// <param name="pts"></param>
        public SegmentShape(List<Coordinate> pts)
            : base()
        {

            this.Configure();    
            this._startNode = new NodeShape(pts[0]);
            this._endNode = new NodeShape(pts[pts.Count - 1]);            

            for (int i = 1; i < pts.Count - 1; i++)
            {
                IVertexShape vt = new VertexShape(pts[i]);
                this.AddVertex(vt);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="startNode"></param>
        /// <param name="endNode"></param>
        /// <param name="pts"></param>
        public SegmentShape(INodeShape startNode, INodeShape endNode, List<IVertexShape> pts)
            : base()
        {
            this.Configure();
            this._startNode = startNode;            
            this._endNode = endNode;           

            foreach (VertexShape vertex in pts)
            {
                this.AddVertex(vertex);
            }
            
        }


        void Configure()
        {             
            this._vertexCollection = new List<IVertexShape>();
            ID = "弧段" + Count.ToString();
            Count++;
        }


        # endregion

        static int Count = 0;
       
        # region 属性

        /// <summary>
        /// shape类型.
        /// </summary>
        public override ShapeType ShapeType
        {
            get
            {
                return ShapeType.Segment;
            }
        }
       
        private List<IVertexShape> _vertexCollection;

        /// <summary>
        /// 所有的顶点集合。不包括节点
        /// </summary>
        public List<IVertexShape> VertexCollection
        {
            get { return _vertexCollection; }
            set { _vertexCollection = value; }
        }


        private INodeShape _startNode;        

        /// <summary>
        /// 起始节点
        /// </summary>
        public INodeShape StartNode
        {
            get { return _startNode; }
            set { _startNode = value; }
        }

        private INodeShape _endNode;

        /// <summary>
        /// 终止节点
        /// </summary>
        public INodeShape EndNode
        {
            get { return _endNode; }
            set { _endNode = value; }
        }


        private IPolygonShape _leftPolygon;

        /// <summary>
        /// 左多边形
        /// </summary>
        public IPolygonShape LeftPolygon
        {
            get { return _leftPolygon; }
            set { _leftPolygon = value; }
        }


        private IPolygonShape _rightPolygon;

        /// <summary>
        /// 右多边形
        /// </summary>
        public IPolygonShape RightPolygon
        {
            get { return _rightPolygon; }
            set { _rightPolygon = value; }
        }
        

        private int _usedNum = 0;

        /// <summary>
        /// 弧段用于构造多边形时使用的次数
        /// </summary>
        public int UsedNum
        {
            get { return _usedNum; }
            set 
            {
                if (value < 0)
                {
                    _usedNum = 0;
                }
                if (value > 2)
                {
                    _usedNum = 2;
                }
                _usedNum = value; 
            }
        }


        private SegmentDirection _firstusedDerection = SegmentDirection.None;

        /// <summary>
        /// 构造多边形时第一次使用的方向
        /// </summary>
        public SegmentDirection FirstusedDerection
        {
            get { return _firstusedDerection; }
            set { _firstusedDerection = value; }
        }

        private SegmentDirection _secondUsedDerection = SegmentDirection.None;

        /// <summary>
        /// 构造多边形时第二次使用的方向
        /// </summary>
        public SegmentDirection SecondUsedDerection
        {
            get { return _secondUsedDerection; }
            set { _secondUsedDerection = value; }
        }
              
        # endregion


        #region 私有方法


      
        #endregion


        #region 继承的方法

        /// <summary>
        /// 获取图形范围
        /// </summary>
        /// <returns></returns>
        protected override IExtent ComputeExtent()
        {
            if (this.StartNode == null || this.EndNode == null) return Qiang.Data.Extent.Empty();

            double minX = Math.Min(this._startNode.Point.X, this._endNode.Point.X);
            double minY = Math.Min(this._startNode.Point.Y, this._endNode.Point.Y);
            double maxX = Math.Max(this._startNode.Point.X, this._endNode.Point.X);
            double maxY = Math.Max(this._startNode.Point.Y, this._endNode.Point.Y);

            foreach (VertexShape vertex in this._vertexCollection)
            {
                minX = minX < vertex.Point.X ? minX : vertex.Point.X;
                minY = minY < vertex.Point.Y ? minY : vertex.Point.Y;
                maxX = maxX > vertex.Point.X ? maxX : vertex.Point.X;
                maxY = maxY > vertex.Point.Y ? maxY : vertex.Point.Y;
            }

            return new Extent(minX, minY, maxX, maxY);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected override IList<Coordinate> ComputeCoordinates()
        {
            List<Coordinate> coors = new List<Coordinate>();
            coors.Add(_startNode.Point);
            foreach (IVertexShape vertex in _vertexCollection)
            {
                coors.Add(vertex.Point);
            }
            coors.Add(_endNode.Point);
            return coors;
        }
       

        #endregion


        #region 公共方法

        /// <summary>
        /// 添加顶点
        /// </summary>
        /// <param name="vertex"></param>
        public void AddVertex(IVertexShape vertex)
        {
            if (vertex == null) return;
            IncludeVertex(vertex);
        }

        /// <summary>
        /// 删除顶点
        /// </summary>
        /// <param name="vertex"></param>
        public void RemoveVertex(IVertexShape vertex)
        {
            if (vertex == null) return;
            ExcludeVertex(vertex);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="vertex"></param>
        private void IncludeVertex(IVertexShape vertex)
        {
            _vertexCollection.Add(vertex);
            vertex.ParentDataset = ParentDataset;
            vertex.ParentSegment = this;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="vertex"></param>
        private void ExcludeVertex(IVertexShape vertex)
        {
            if (_vertexCollection.Remove(vertex) == true)
            {
                vertex.ParentDataset = null;
                vertex.ParentSegment = null;
            }
        }


        #endregion


        public override IGeometry ToGeometry()
        {
            ILineString line = new LineString(Coordinates.ToArray());
            return line;
        }

        public override object Clone()
        {
            return base.Clone();
        }

    }
}
